/**
 * 请求队列管理
 * 处理请求的优先级、并发控制和取消
 */

class RequestQueue {
  constructor(options = {}) {
    this.options = {
      maxConcurrent: 6,
      priorityLevels: 3,
      ...options
    };
    
    // 请求队列，按优先级分组
    this.queues = Array(this.options.priorityLevels)
      .fill(null)
      .map(() => []);
    
    // 活跃的请求任务
    this.activeRequests = new Map();
    
    // 取消的请求ID集合
    this.canceledRequests = new Set();
    
    // 当前活跃请求计数
    this.activeCount = 0;
    
    // 是否正在处理队列
    this.isProcessing = false;
  }

  /**
   * 添加请求到队列
   * @param {Function} requestTask 请求任务函数
   * @param {Object} options 选项，包含优先级和请求ID
   * @returns {Promise} 请求Promise
   */
  add(requestTask, options = {}) {
    const { priority = 1, requestId } = options;
    
    // 确保优先级在有效范围内
    const normalizedPriority = Math.min(
      Math.max(Math.floor(priority), 0),
      this.options.priorityLevels - 1
    );
    
    // 创建一个Promise，以便在执行请求时解析
    return new Promise((resolve, reject) => {
      // 构建请求对象
      const request = {
        requestTask,
        requestId,
        resolve,
        reject,
        timestamp: Date.now()
      };
      
      // 如果请求已经被取消，直接拒绝
      if (this.canceledRequests.has(requestId)) {
        reject(new Error('Request was canceled'));
        this.canceledRequests.delete(requestId);
        return;
      }
      
      // 加入对应优先级的队列
      this.queues[normalizedPriority].push(request);
      
      // 开始处理队列
      this._processQueue();
    });
  }

  /**
   * 取消指定ID的请求
   * @param {String} requestId 请求ID
   */
  cancel(requestId) {
    if (!requestId) return;
    
    // 如果请求正在活跃，取消它
    if (this.activeRequests.has(requestId)) {
      const request = this.activeRequests.get(requestId);
      if (request && request.abort && typeof request.abort === 'function') {
        request.abort(new Error('Request canceled'));
      }
      this.activeRequests.delete(requestId);
      this.activeCount = Math.max(0, this.activeCount - 1);
    }
    
    // 将请求ID加入已取消集合，以便在尚未开始的请求尝试启动时拒绝它
    this.canceledRequests.add(requestId);
    
    // 从所有队列中移除该请求
    for (let i = 0; i < this.queues.length; i++) {
      this.queues[i] = this.queues[i].filter(req => {
        if (req.requestId === requestId) {
          req.reject(new Error('Request canceled'));
          return false;
        }
        return true;
      });
    }
  }

  /**
   * 取消所有请求
   * @param {String} reason 取消原因
   */
  cancelAll(reason = 'All requests canceled') {
    const cancelError = new Error(reason);
    
    // 取消所有活跃的请求
    this.activeRequests.forEach((request, requestId) => {
      if (request && request.abort && typeof request.abort === 'function') {
        request.abort(cancelError);
      }
    });
    
    // 清空活跃请求Map
    this.activeRequests.clear();
    this.activeCount = 0;
    
    // 从所有队列中拒绝并移除所有请求
    for (let i = 0; i < this.queues.length; i++) {
      this.queues[i].forEach(req => {
        req.reject(cancelError);
      });
      this.queues[i] = [];
    }
    
    // 清空已取消集合
    this.canceledRequests.clear();
  }

  /**
   * 获取当前活跃请求数量
   * @returns {Number} 活跃请求数量
   */
  getActiveCount() {
    return this.activeCount;
  }

  /**
   * 获取当前队列中等待的请求数量
   * @returns {Number} 等待的请求数量
   */
  getPendingCount() {
    return this.queues.reduce((total, queue) => total + queue.length, 0);
  }

  /**
   * 处理队列中的请求
   * @private
   */
  _processQueue() {
    // 如果已经在处理队列或没有活跃槽位，则返回
    if (this.isProcessing || this.activeCount >= this.options.maxConcurrent) {
      return;
    }
    
    // 标记为正在处理
    this.isProcessing = true;
    
    try {
      // 计算可用的并发槽位
      const availableSlots = this.options.maxConcurrent - this.activeCount;
      
      if (availableSlots <= 0) {
        return;
      }
      
      // 按优先级从高到低处理队列
      for (let priority = 0; priority < this.queues.length; priority++) {
        const queue = this.queues[priority];
        
        // 如果当前优先级队列为空，继续下一个优先级
        if (queue.length === 0) {
          continue;
        }
        
        // 处理当前优先级队列中的请求，直到没有可用槽位或队列为空
        while (this.activeCount < this.options.maxConcurrent && queue.length > 0) {
          const request = queue.shift();
          
          // 检查请求是否被取消
          if (request.requestId && this.canceledRequests.has(request.requestId)) {
            request.reject(new Error('Request was canceled'));
            this.canceledRequests.delete(request.requestId);
            continue;
          }
          
          // 增加活跃计数
          this.activeCount++;
          
          // 执行请求任务
          this._executeRequest(request);
        }
        
        // 如果没有更多可用槽位，退出循环
        if (this.activeCount >= this.options.maxConcurrent) {
          break;
        }
      }
    } finally {
      // 标记为不再处理
      this.isProcessing = false;
      
      // 如果还有请求和可用槽位，继续处理队列
      if (this.getPendingCount() > 0 && this.activeCount < this.options.maxConcurrent) {
        this._processQueue();
      }
    }
  }

  /**
   * 执行请求任务
   * @param {Object} request 请求对象
   * @private
   */
  _executeRequest(request) {
    const { requestTask, requestId, resolve, reject } = request;
    
    try {
      // 执行请求任务
      const promise = requestTask();
      
      // 如果请求ID存在，将请求添加到活跃Map
      if (requestId) {
        // 如果请求任务返回的对象有abort方法，将其保存以便取消
        if (promise && promise.abort && typeof promise.abort === 'function') {
          this.activeRequests.set(requestId, {
            promise,
            abort: promise.abort.bind(promise)
          });
        } else {
          this.activeRequests.set(requestId, { promise });
        }
      }
      
      // 处理请求完成
      promise
        .then(result => {
          // 移除活跃请求
          if (requestId) {
            this.activeRequests.delete(requestId);
          }
          
          // 减少活跃计数
          this.activeCount = Math.max(0, this.activeCount - 1);
          
          // 解析结果
          resolve(result);
          
          // 处理后续队列
          this._processQueue();
        })
        .catch(error => {
          // 移除活跃请求
          if (requestId) {
            this.activeRequests.delete(requestId);
          }
          
          // 减少活跃计数
          this.activeCount = Math.max(0, this.activeCount - 1);
          
          // 拒绝结果
          reject(error);
          
          // 处理后续队列
          this._processQueue();
        });
    } catch (error) {
      // 处理同步错误
      
      // 移除活跃请求
      if (requestId) {
        this.activeRequests.delete(requestId);
      }
      
      // 减少活跃计数
      this.activeCount = Math.max(0, this.activeCount - 1);
      
      // 拒绝结果
      reject(error);
      
      // 处理后续队列
      this._processQueue();
    }
  }
}

// 添加具名导出
export { RequestQueue };
export default RequestQueue; 